package com.xq.shop.interceptor;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xq.shop.config.Redis;
import com.xq.shop.dao.domain.entity.LoginLog;
import com.xq.shop.service.ILoginLogService;
import com.xq.shop.vo.LoginInfo;
import com.xq.shop.vo.UserVo;
import enums.ResultCodes;
import exception.BusinessDataException;
import exception.BusinessException;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import utils.BaseConstants;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * @author gaoxiaojin
 */
@Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    private ILoginLogService loginLogService;

    @Autowired
    private Redis redis;

    @Value("${api.sso.allow-urls}")
    private String[] allowUrls;


    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        String requestUrl = request.getRequestURI();
        request.setAttribute("ignore", "no");
        if (null != allowUrls && allowUrls.length >= 1) {
            for (String url : allowUrls) {
                if (requestUrl.contains(url)) {
                    request.setAttribute("ignore", "all");
                    return true;
                }
            }
        }
        String token = AuthInterceptor.getToken(request);
        // redis获取不到token则返回无效令牌
        token = redis.existsLike(token, 1);
        if (Objects.isNull(token)) {
            throw new BusinessException(ResultCodes.TOKEN_EMPTY);
        }
        UserVo vo = (UserVo) redis.get(token);
        // 对应token查出来的用户信息为空，表示账号已在其他地方登录，返回其他地方的登录信息
        if (Objects.isNull(vo)) {
            Integer userId = Integer.parseInt(token.substring(token.length() - 2, token.length() - 1));
            LambdaQueryWrapper<LoginLog> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(LoginLog::getUserId, userId).last("LIMIT 1");
            LoginLog loginLog = loginLogService.getOne(wrapper);
            LoginInfo info = new LoginInfo();
            info.setArea(loginLog.getArea());
            info.setIp(loginLog.getIp());
            info.setBrowser(loginLog.getBrowser());
            info.setSystem(loginLog.getDSystem());
            throw new BusinessDataException(ResultCodes.ALREADY_LOGIN, info);
        }
        // 刷新token过期时长
        redis.set(token, vo, BaseConstants.TOKEN_TIME);
        return true;
    }


    public static String getToken(HttpServletRequest request) {
        String token = request.getHeader("QwToken");
        if (Objects.isNull(token)) {
            throw new BusinessException(ResultCodes.TOKEN_EMPTY);
        }
        return token;
    }
}
